package com.mdhw.mili.service.impl;

import cn.hutool.core.codec.Base64;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.symmetric.AES;
import cn.hutool.http.HttpException;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.mdhw.mili.service.MiliTokenService;
import com.mdhw.mili.vo.MiliTokenVo;
import org.springframework.stereotype.Service;

import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

@Service
public class MiliTokenServiceImpl implements MiliTokenService {




    private static String GET_TOKEN_APPID = "hjj-test";
    private static String GET_TOKEN_APPSECRET = "f39bdb5e970b49c2";
    private static String GET_TOKEN_RANDOMSTR = "";
    private static String GET_TOKEN_URL = "http://testcloud.aurine.cn:28088/auth/oauth/token";
    private static String GET_TOKEN_USERNAME = "18950462412";
    private static String GET_TOKEN_PASSWORD = "6iyicH#DFB";
    private static String GET_TOKEN_GRANT_TYPE = "password";
    private static String PROJECT_UUID = "48bea48c8d6a46cd84759bce498e610b";
    /**
     * 获取 Authorization
     *
     * @return
     */
    //进行Base64位加密
    public static String getAuthorization() {
        StringBuffer strB = new StringBuffer();
        strB.append(GET_TOKEN_APPID).append(":").append(GET_TOKEN_APPSECRET);
        String encode = Base64.encode(strB.toString());
        String Authorization = "Basic " + encode;
        return Authorization;
    }

    /**
     * 获取当前时间戳 Timestamp参数
     *
     * @return
     */
    public static String getTimestamp() {
        //获取当前当前 unix 时间戳
        return Long.toString(System.currentTimeMillis() / 1000L);
    }


    /**
     * AES-CBC-128-ZeroPadding  AES加密算法
     * <p>
     * iv 偏移量就是 appsecret
     */
    //加密
    private static String encryptFromString(String data, Mode mode, Padding padding) {
        AES aes;
        if (Mode.CBC == mode) {
            aes = new AES(mode, padding,
                    new SecretKeySpec(GET_TOKEN_APPSECRET.getBytes(), "AES"),
                    new IvParameterSpec(GET_TOKEN_APPSECRET.getBytes()));
        } else {
            aes = new AES(mode, padding,
                    new SecretKeySpec(GET_TOKEN_APPSECRET.getBytes(), "AES"));
        }
        return aes.encryptBase64(data, StandardCharsets.UTF_8);
    }


    /**
     * 随机种子
     * randomstr
     */
    public static String randomString() {
        String s = "0123456789abcdef";
        StringBuffer strB = new StringBuffer();
        for (int i = 10; i > 0; i--) {
            strB.append(s.charAt((int) Math.floor(Math.random() * s.length())));
        }
        return strB.toString();
    }

    /**
     * 获得Sign参数
     */
    public static String getSign(String timestamp) {

        //随机种子
        String s = randomString();
        GET_TOKEN_RANDOMSTR = s;
        String body = "randomStr=" + s;
        String sign = GET_TOKEN_APPID + timestamp + body;
//        System.out.println(sign);
        //进行加密
        sign = encryptFromString(sign, Mode.CBC, Padding.ZeroPadding);
 //       System.out.println(sign);
        return sign;
    }

    /**
     * 获得密码  password
     * @param
     */
    public static String getPassword(String password){
        return encryptFromString(password, Mode.CBC, Padding.ZeroPadding);
    }

    @Override
    public MiliTokenVo getMiliToken() {
        //指定URL
        String url = GET_TOKEN_URL;

        //存放请求头，可以存放多个请求头
        HashMap<String, String> headers = new HashMap<String, String>();


        headers.put("Authorization", getAuthorization());
        //获取时间戳
        String timestamp = getTimestamp();
        headers.put("Timestamp", timestamp);
        System.out.println(timestamp);
        headers.put("Sign", getSign(timestamp));


        //存放参数
        Map<String, Object> map = new HashMap<>();
        map.put("username", GET_TOKEN_USERNAME);
        map.put("password", getPassword(GET_TOKEN_PASSWORD));

        // 构建请求体字符串
        StringBuilder bodyBuilder = new StringBuilder();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            try {
                if (bodyBuilder.length() > 0) {
                    bodyBuilder.append("&");
                }
                bodyBuilder.append(URLEncoder.encode(entry.getKey(), "UTF-8"))
                        .append("=")
                        .append(URLEncoder.encode(entry.getValue().toString(), "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                // UTF-8 编码是Java标准支持的，所以这里通常不会抛出异常
                throw new RuntimeException(e);
            }
        }

        String requestBody = bodyBuilder.toString();

        // 计算Content-Length
        byte[] requestBodyBytes = requestBody.getBytes(StandardCharsets.UTF_8);
        int contentLength = requestBodyBytes.length;

        // 打印Content-Length，或者在实际请求中设置它
        System.out.println("Content-Length: " + contentLength);

        //可以通过request.getParameter()方法来获取url地址栏中的参数
        url = url + "?randomStr=" + GET_TOKEN_RANDOMSTR + "&grant_type=" + GET_TOKEN_GRANT_TYPE;


        //结果
        String result = null;

        //发送Post请求并接收响应数据
        try {
            result = HttpUtil.createPost(url)
                    .addHeaders(headers)
                    .form(map)
                    .execute()
                    .body();
        } catch (HttpException e) {
            System.out.println("请求超时");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        MiliTokenVo miliTokenVo = JSONObject.parseObject(result, MiliTokenVo.class);
        return miliTokenVo;
    }

    @Override
    public String buildMiliToken() {
        MiliTokenVo miliToken = this.getMiliToken();
        String accessToken = miliToken.getAccess_token();
        return "Bearer " +accessToken;
    }

}
